#include "tablemodel.h"

TableModel::TableModel(QObject *parent)
    : QAbstractTableModel(parent)
{
    m_data.append(new TableRowItem {0, "Chen", 0, 100, true});
}

TableModel::~TableModel()
{
    clear();
}

QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(role == Qt::DisplayRole) {
        if(orientation == Qt::Horizontal) {
            if(section >= 0 && section < m_horizontalHeaders.size())
                return m_horizontalHeaders.at(section);
        }
        else if(orientation == Qt::Vertical) {
            if(section >= 0 && section < m_verticalHeaders.size())
                return m_verticalHeaders.at(section);
        }
    } else if(role == Qt::TextAlignmentRole) {
        return Qt::AlignCenter;
    }


    return QVariant();
}

bool TableModel::setHeaderData(int section,
                               Qt::Orientation orientation,
                               const QVariant &value,
                               int role)
{
    if (value != headerData(section, orientation, role)) {
        if(role == Qt::DisplayRole || role == Qt::EditRole) {
            bool changed = false;
            if(orientation == Qt::Horizontal) {
                if(section >= 0 && section < m_horizontalHeaders.size()) {
                    m_horizontalHeaders[section] = value.toString();
                    changed = true;
                }
            }
            else if(orientation == Qt::Vertical) {
                if(section >= 0 && section < m_verticalHeaders.size()) {
                    m_verticalHeaders[section] = value.toString();
                    changed = true;
                }
            }
            if(changed) {
                emit headerDataChanged(orientation, section, section);
                return true;
            }
        }
    }
    return false;
}

int TableModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;

    return m_data.size();
}

int TableModel::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;

    return m_horizontalHeaders.size();
}

bool TableModel::hasChildren(const QModelIndex &parent) const
{
    return false;
}

bool TableModel::canFetchMore(const QModelIndex &parent) const
{
    return false;
}

void TableModel::fetchMore(const QModelIndex &parent)
{
    // FIXME: Implement me!
}

QVariant TableModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();
    if(role == Qt::DisplayRole || role == Qt::EditRole) {
        if(index.row() < m_data.size() && index.column() < TableRowItem::TypeNum) {
            return m_data.at(index.row())->get(index.column(), role);
        }
    } else if(role == Qt::TextAlignmentRole) {
        return Qt::AlignCenter;
    }
    return QVariant();
}

bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (data(index, role) != value) {
        bool changed = false;
        if(role == Qt::DisplayRole || role == Qt::EditRole) {
            if(index.row() < m_data.size() && index.column() < TableRowItem::TypeNum) {
                changed = m_data.at(index.row())->set(index.column(), value, role);
            }
        }
        if(changed)
            emit dataChanged(index, index, {role});
        return changed;
    }
    return false;
}

Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::NoItemFlags;
    if(index.column() == TableRowItem::Progress || index.column() == TableRowItem::Checked)
        return QAbstractItemModel::flags(index) & ~Qt::ItemIsEditable;
    return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}

bool TableModel::insertRows(int row, int count, const QModelIndex &parent)
{
    if(row > m_data.size())
        return false;
    beginInsertRows(parent, row, row + count - 1);
    for(int i = 0; i < count; i ++)
        m_data.insert(row+i, new TableRowItem);
    endInsertRows();
    return true;
}

bool TableModel::insertColumns(int column, int count, const QModelIndex &parent)
{
    beginInsertColumns(parent, column, column + count - 1);
    // FIXME: Implement me!
    endInsertColumns();
    return true;
}

bool TableModel::removeRows(int row, int count, const QModelIndex &parent)
{
    if(row >= m_data.size())
        return false;
    beginRemoveRows(parent, row, row + count - 1);
    for(int i = 0; i < count; i ++) {
        if(row > m_data.size())
            break;
        auto p = m_data.takeAt(row);
        if(p)
            delete p;
    }
    endRemoveRows();
    return true;
}

bool TableModel::removeColumns(int column, int count, const QModelIndex &parent)
{
    beginRemoveColumns(parent, column, column + count - 1);
    // FIXME: Implement me!
    endRemoveColumns();
    return true;
}

QStringList TableModel::horizontalHeaders() const
{
    return m_horizontalHeaders;
}

void TableModel::setHorizontalHeaders(const QStringList &newHorizontalHeaders)
{
    m_horizontalHeaders = newHorizontalHeaders;
    if(newHorizontalHeaders.size() > 0)
        emit headerDataChanged(Qt::Horizontal, 0, newHorizontalHeaders.size()-1);
}

QStringList TableModel::verticalHeaders() const
{
    return m_verticalHeaders;
}

void TableModel::setVerticalHeaders(const QStringList &newVerticalHeaders)
{
    m_verticalHeaders = newVerticalHeaders;
    if(newVerticalHeaders.size() > 0)
        emit headerDataChanged(Qt::Vertical, 0, newVerticalHeaders.size()-1);
}

bool TableModel::appendRow(const TableRowItem &item)
{
    if(insertRow(rowCount())) {
        *m_data.last() = item;
        // emit dataChanged(index(rowCount()-1, 0), index(rowCount()-1, columnCount()-1));
        return true;
    }
    return false;

}

void TableModel::clear()
{
    removeRows(0, rowCount());
}
